package com.ccrfid.rmc6.service.video;

import com.ccrfid.rmc6.appconfig.exception.pojo.AppException;
import com.ccrfid.rmc6.appconfig.exception.pojo.CustomErrors;
import com.ccrfid.rmc6.entity.poi.PoiCameraEntity;
import com.ccrfid.rmc6.entity.video.VideoCameraEntity;
import com.ccrfid.rmc6.entity.video.VideoCameraView;
import com.ccrfid.rmc6.pojo.Constants;
import com.ccrfid.rmc6.pojo.dto.VideoCameraDto;
import com.ccrfid.rmc6.repository.poi.PoiCameraRepository;
import com.ccrfid.rmc6.repository.search.SearchCriteria;
import com.ccrfid.rmc6.repository.video.VideoCameraRepository;
import com.ccrfid.rmc6.repository.video.VideoCameraViewRepository;
import com.ccrfid.rmc6.util.NetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import javax.ws.rs.core.Response;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.regex.Pattern;

@Service
@Transactional
public class VideoCameraServiceImpl implements VideoCameraService {
    private static final Logger logger = LoggerFactory.getLogger(VideoCameraServiceImpl.class);
    @Autowired
    private VideoCameraRepository videoCameraRepository;
    @Autowired
    private VideoCameraViewRepository videoCameraViewRepository;
    @Autowired
    private PoiCameraRepository poiCameraRepository;
    @Autowired
    private VideoSyncService videoSyncService;
    @Autowired
    private HikArtemisService hikArtemisService;
    @Autowired
    private Open8200Service open8200Service;

    @Override
    public List<VideoCameraView> getAllVideoCameraInfo(SearchCriteria criteria, Sort sort) {
        return videoCameraViewRepository.search(criteria, sort);
    }

    @Override
    public Page<VideoCameraView> getVideoCameraInfoPage(SearchCriteria criteria, Pageable pageable) {
        Page<VideoCameraView> page = videoCameraViewRepository.search(criteria, pageable);
        return page;
    }

    @Override
    public VideoCameraEntity getVideoCamera(Long cameraId) {
        return videoCameraRepository.getById(cameraId);
    }

    @Override
    public VideoCameraDto getCameraLinkageInfo(Long cameraId, String clientIpAddr) {
        VideoCameraEntity cameraEntity = videoCameraRepository.getById(cameraId);
        if (cameraEntity != null) {
            String ip = NetUtil.getMatchIPAddr(clientIpAddr, cameraEntity.getIp(), cameraEntity.getIp2());
            VideoCameraDto dto = new VideoCameraDto();
            dto.setRescode(cameraEntity.getCameraSn());
            dto.setName(cameraEntity.getCameraName());
            dto.setVersion(videoSyncService.getIVersion(cameraEntity.getCameraVersion()));
            dto.setIp(ip);
            dto.setPort(cameraEntity.getPort());
            dto.setUsername(cameraEntity.getUsername());
            dto.setPassword(cameraEntity.getPasswd());
            dto.setChannel(cameraEntity.getChannelNum());
            dto.setCameraId(cameraId);
            return dto;
        } else {
            return null;
        }
    }

    @Override
    public String getPreviewUrl(Long cameraId, String protocol, String clientIpAddr) {
        VideoCameraEntity cameraEntity = videoCameraRepository.getById(cameraId);
        String ip = NetUtil.getMatchIPAddr(clientIpAddr, cameraEntity.getIp(), cameraEntity.getIp2());
        if (cameraEntity != null) {
            if (cameraEntity.getCameraVersion().equals(Constants.VIDEO_VERSION.HK_ARTEMIS_B.id)
                    || cameraEntity.getCameraVersion().equals(Constants.VIDEO_VERSION.HK_ARTEMIS_C.id)) {
                String playUrl = hikArtemisService.getPreviewURL(cameraEntity.getCameraSn(), protocol, 0, 0);
                return changeUrl(playUrl, ip);
            } else if (cameraEntity.getCameraVersion().equals(Constants.VIDEO_VERSION.HK_OPEN8200.id)) {
                String playUrl = open8200Service.getPreviewURL(cameraEntity.getCameraSn(), protocol, 0);
                return changeUrl(playUrl, ip);
            }
        }
        return "";
    }

    private static String changeUrl(String playUrl, String newIp) {
        if (playUrl != null) {
            String playIp = NetUtil.getURLIp(playUrl);
            if (NetUtil.getIPMatchDegree(playIp, newIp) > 6) {
                logger.debug("playUrl: {}", playUrl);
                return playUrl;
            } else {
                Pattern pattern = Pattern.compile("//*.*.*.*:");
                String newUrl = pattern.matcher(playUrl).replaceAll("//" + newIp + ":");
                logger.debug("playUrl: {}, newUrl: {}", playUrl, newUrl);
                return newUrl;
            }
        }
        return "";
    }

    @Override
    public String getPlaybackUrl(Long cameraId, String protocol, Timestamp startTime, Timestamp stopTime, String clientIpAddr) {
        VideoCameraEntity cameraEntity = videoCameraRepository.getById(cameraId);
        String ip = NetUtil.getMatchIPAddr(clientIpAddr, cameraEntity.getIp(), cameraEntity.getIp2());
        if (cameraEntity != null) {
            if (cameraEntity.getCameraVersion().equals(Constants.VIDEO_VERSION.HK_ARTEMIS_B.id)
                    || cameraEntity.getCameraVersion().equals(Constants.VIDEO_VERSION.HK_ARTEMIS_C.id)) {
                DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS+08:00");
                String playUrl = hikArtemisService.getPlaybackURL(cameraEntity.getCameraSn(), protocol,
                        dateFormat.format(startTime), dateFormat.format(stopTime), cameraEntity.getRecordLocation());
                return changeUrl(playUrl, ip);
                //永康特殊回放
//                return hikArtemisService.getPlaybackURL2(cameraEntity.getCameraSn(), protocol,
//                        dateFormat.format(startTime), dateFormat.format(stopTime), cameraEntity.getRecordLocation());
            } else if (cameraEntity.getCameraVersion().equals(Constants.VIDEO_VERSION.HK_OPEN8200.id)) {
                String playUrl = open8200Service.getPlaybackURL(cameraEntity.getCameraSn(), protocol,
                        startTime, stopTime, cameraEntity.getRecordLocation());
                return changeUrl(playUrl, ip);
            }
        }
        return "";
    }

    @Override
    public String getVideoClientPlayUrl(String playType, List<Long> cameraIdList, Integer miniUI, Integer clear,
                                        Integer wndSelect, Integer httpsFlag, Timestamp startTime, Timestamp stopTime) {
        return open8200Service.getVideoClientPlayUrl(
                playType, cameraIdList, miniUI, clear, wndSelect, httpsFlag, startTime, stopTime);
    }

    private String getCameraList(List<Long> cameraIdList, Timestamp startTime, Timestamp stopTime) {
        List<VideoCameraEntity> cameraList = videoCameraRepository.getAllByIdIn(cameraIdList);
        if (cameraList != null && cameraList.size() > 0) {
            String content = "";
            String postfix = "";
            if (startTime != null && stopTime != null) {
                postfix = "_" + (startTime.getTime() / 1000) + "_" + (stopTime.getTime() / 1000);
            }
            for (VideoCameraEntity cameraEntity : cameraList) {
                content += cameraEntity.getCameraSn() + postfix + ",";
            }
            return content.substring(0, content.length() - 1);
        }
        return "";
    }

    @Override
    public VideoCameraEntity createVideoCamera(VideoCameraEntity entity) throws AppException {
        if (videoCameraRepository.existsByCameraSn(entity.getCameraSn())) {
            throw new AppException(Response.Status.CONFLICT.getStatusCode(),
                    CustomErrors.camera_sn_conflict.getCode(), CustomErrors.camera_sn_conflict.getReason(), "");
        }
        return videoCameraRepository.save(entity);
    }

    @Override
    public VideoCameraEntity updateVideoCamera(Long cameraId, VideoCameraEntity entity) throws AppException {
        if (!videoCameraRepository.existsById(cameraId)) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        if (!cameraId.equals(entity.getId())) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.different_args.getCode(), CustomErrors.different_args.getReason(), "");
        }
        if (videoCameraRepository.existsByCameraSnAndIdNot(entity.getCameraSn(), cameraId)) {
            throw new AppException(Response.Status.CONFLICT.getStatusCode(),
                    CustomErrors.camera_sn_conflict.getCode(), CustomErrors.camera_sn_conflict.getReason(), "");
        }
        return videoCameraRepository.save(entity);
    }

    @Override
    public PoiCameraEntity getCameraPosition(Long cameraId) throws AppException {
        if (!videoCameraRepository.existsById(cameraId)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        return poiCameraRepository.getByCameraId(cameraId);
    }

    @Override
    public PoiCameraEntity updateCameraPosition(Long cameraId, PoiCameraEntity entity) throws AppException {
        if (!videoCameraRepository.existsById(cameraId)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        if (poiCameraRepository.existsByCameraId(cameraId)) {
            PoiCameraEntity poiCameraEntity = poiCameraRepository.getByCameraId(cameraId);
            poiCameraEntity.setCameraShape(entity.getCameraShape());
            poiCameraEntity.setDirection(entity.getDirection());
            poiCameraEntity.setFloorNumber(entity.getFloorNumber());
            poiCameraEntity.setPos(entity.getPos());
            poiCameraEntity.setPermissionLevel(entity.getPermissionLevel());
            return poiCameraRepository.save(poiCameraEntity);
        } else {
            entity.setCameraId(cameraId);
            return poiCameraRepository.save(entity);
        }
    }

    @Override
    public Boolean deleteCameraPosition(Long cameraId) {
        if (poiCameraRepository.existsByCameraId(cameraId)) {
            poiCameraRepository.deleteByCameraId(cameraId);
        }
        return true;
    }

    @Override
    public int deleteVideoCamerasInfo(List<Long> idList) {
        int count = 0;
        for (Long id : idList) {
            if (videoCameraRepository.existsById(id)) {
                count++;
            }
        }
        if (count > 0) {
            poiCameraRepository.deleteByCameraIdIn(idList);
            videoCameraRepository.deleteByIdIn(idList);
        }
        return count;
    }
}
